 
package com.junitUtil.aspect;	
import com.junitUtil.annotions.AopTarget;
import com.junitUtil.spring.DecoratorBeanFactory;

import java.io.File;
import java.io.StringBufferInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.aspectj.bridge.Constants;
import org.aspectj.weaver.loadtime.DefaultWeavingContext;
import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.loadtime.definition.DocumentParser;
import org.aspectj.weaver.loadtime.definition.Definition.AdviceKind;
import org.aspectj.weaver.loadtime.definition.Definition.ConcreteAspect;
import org.aspectj.weaver.loadtime.definition.Definition.PointcutAndAdvice;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;
import org.aspectj.weaver.tools.WeavingAdaptor;



/**
 * 重写了父类的getDefinitions 
 * 将单元测试的项目需要在增加/META-INF/aop.xml文件改成了代码写死
 * 
 **/
public class WeavingContextLocal extends DefaultWeavingContext{

    private static Trace trace = TraceFactory.getTraceFactory().getTrace(WeavingContextLocal.class);
    private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML;

    /** 
     * <p>Title: </p> 
     * <p>Description: </p> 
     * @param loader 
     */
    
    public WeavingContextLocal(ClassLoader loader) {
        
        super(loader);
    }

    /**
     * Simply call weaving adaptor back to parse aop.xml
     * 
     * @param weaver
     * @param loader
     */
    public List<Definition> getDefinitions(final ClassLoader loader, final WeavingAdaptor adaptor) {
        if (trace.isTraceEnabled()) {
            trace.enter("getDefinitions", this, new Object[] { "goo", adaptor });
        }

        List<Definition> definitions = parseDefinitions(loader);
        try {
            String weaverTarget="";
            String aspectClass=""; 
            try {
                Object testInstance=DecoratorBeanFactory.getInstance().getBean(DecoratorBeanFactory.JUNIT_TEST_NAME);
                weaverTarget = testInstance.getClass().getAnnotation(AopTarget.class).target();
                aspectClass= testInstance.getClass().getAnnotation(AopTarget.class).aspectClass();
            } catch (Exception e) {
            	throw new  Exception("AopTarget need");
            }
            StringBuilder sb=new StringBuilder();
            sb.append("<aspectj>")
//                         .append("<weaver options=\"-verbose -Xlintfile:pathToAResource  -showWeaveInfo -Xreweavable \">")
                           .append("<weaver options=\" -Xreweavable \"> ")
                                .append(" <include within=\""+weaverTarget+"\"/> ")
                          .append("</weaver> ")
                          .append("<aspects>")
                              .append("<aspect name=\""+aspectClass+"\"/> ")
                          .append("</aspects> ")
               .append(" </aspectj> ");
            Definition definition=DocumentParserLocal.parse(new StringBufferInputStream(sb.toString()));
            ConcreteAspect concreteAspect=new ConcreteAspect("ext",null);
        	Object testInstance=DecoratorBeanFactory.getInstance().getBean( DecoratorBeanFactory.JUNIT_TEST_NAME );
			// 修改 value 属性值
			 String value= testInstance.getClass().getDeclaredAnnotation(AopTarget.class).pointCut();
            concreteAspect.pointcutsAndAdvice.add(new PointcutAndAdvice(AdviceKind.Before,value,aspectClass,"checkEntity(JoinPoint joinPoint )"));
            definition.getConcreteAspects().add(concreteAspect);
            definitions.add(definition);        } catch (Exception e) {
            e.printStackTrace( );
        }
        if (trace.isTraceEnabled()) {
            trace.exit("getDefinitions", definitions);
        }
        return definitions;
    }
    
    List<Definition> parseDefinitions(final ClassLoader loader) {
        if (trace.isTraceEnabled()) {
            trace.enter("parseDefinitions", this);
        }

        List<Definition> definitions = new ArrayList<Definition>();
        try {
            if (loader.equals(ClassLoader.getSystemClassLoader())) {
                String file = System.getProperty("aj5.def", null);
                if (file != null) {
                    definitions.add(DocumentParser.parse((new File(file)).toURL()));
                }
            }

            String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration", AOP_XML);
            if (trace.isTraceEnabled()) {
                trace.event("parseDefinitions", this, resourcePath);
            }

            StringTokenizer st = new StringTokenizer(resourcePath, ";");

            while (st.hasMoreTokens()) {
                String nextDefinition = st.nextToken();
                if (nextDefinition.startsWith("file:")) {
                    try {
                        String fpath = new URL(nextDefinition).getFile();
                        File configFile = new File(fpath);
                        if (!configFile.exists()) {
                        } else {
                            definitions.add(DocumentParser.parse(configFile.toURL()));
                        }
                    } catch (MalformedURLException mue) {
                    }
                } else {
                    Enumeration<URL> xmls =  getResources(nextDefinition);
                    // System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader);

                    Set<URL> seenBefore = new HashSet<URL>();
                    while (xmls.hasMoreElements()) {
                        URL xml = xmls.nextElement();
                        if (trace.isTraceEnabled()) {
                            trace.event("parseDefinitions", this, xml);
                        }
                        if (!seenBefore.contains(xml)) {
                            definitions.add(DocumentParser.parse(xml));
                            seenBefore.add(xml);
                        } 
                    }
                }
            }
           
        } catch (Exception e) {
            definitions.clear();
        }

        if (trace.isTraceEnabled()) {
            trace.exit("parseDefinitions", definitions);
        }
        return definitions;
    }
    
  
    
}
 